package com.arpa.oms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.jpush.api.report.UsersResult;
import com.arpa.ntocc.common.common.cache.PartyCache;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.CommonUtil;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.oms.domain.dto.OmsPurchaseReturnDTO;
import com.arpa.oms.domain.entity.*;
import com.arpa.oms.domain.enums.OrderStatusEnum;
import com.arpa.oms.domain.enums.PurchaseTypeEnum;
import com.arpa.oms.domain.vo.OmsPurchaseReturnItemVO;
import com.arpa.oms.domain.vo.OmsPurchaseReturnVO;
import com.arpa.oms.mapper.OmsPurchaseReturnMapper;
import com.arpa.oms.service.*;
import com.arpa.wms.cache.GoodsCache;
import com.arpa.wms.cache.SupplierCache;
import com.arpa.wms.cache.WarehouseCache;
import com.arpa.wms.common.util.OrderIdGeneratorUtil;
import com.arpa.wms.domain.entity.Delivery;
import com.arpa.wms.domain.entity.DeliveryItem;
import com.arpa.wms.domain.entity.Goods;
import com.arpa.wms.domain.entity.Warehouse;
import com.arpa.wms.domain.enums.DeliveryStatusEnum;
import com.arpa.wms.domain.enums.DeliveryTypeEnum;
import com.arpa.wms.domain.enums.InboundStatusEnum;
import com.arpa.wms.service.IDeliveryItemService;
import com.arpa.wms.service.IDeliveryService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * OMS采购退货单 服务实现类
 * </p>
 *
 * @author LEO
 * @since 2020-11-17
 */
@Log4j2(topic = "business")
@Service
public class OmsPurchaseReturnServiceImpl extends ServiceImpl<OmsPurchaseReturnMapper, OmsPurchaseReturn> implements IOmsPurchaseReturnService {

    private final OmsPurchaseReturnItemServiceImpl omsPurchaseReturnItemService;
    private final   IOmsPurchaseReturnItemService iOmsPurchaseReturnItemService;
    private final IOmsInboundService inboundService;
    private final IOmsInboundItemService inboundItemService;
    /**
     * XYTODO TODO 计算百分数，除以100时计算的常量    后期可统一放到公用文件中
     */
    public static final BigDecimal DECIMAL100 = new BigDecimal("100");
    @Resource
    private PartyCache partyCache;
    private final IPurchaseService purchaseService;
    @Autowired
    @Lazy
    private OmsSettlementServiceImpl omsSettlementService;
    @Autowired
    private IDeliveryService deliveryService;
    @Autowired
    private IDeliveryItemService deliveryItemService;

    private final IOmsInventoryService inventoryService;
    private final IPurchaseItemService purchaseItemService;
    @Autowired
    private GoodsCache goodsCache;
    @Resource
    private WarehouseCache warehouseCache;
    @Resource
    private SupplierCache supplierCache;

    private final IOmsInventoryService iOmsInventoryService;
    public OmsPurchaseReturnServiceImpl(OmsPurchaseReturnItemServiceImpl omsPurchaseReturnItemService,
                                        IOmsPurchaseReturnItemService iOmsPurchaseReturnItemService, IOmsInboundService inboundService, IOmsInboundItemService inboundItemService, IPurchaseService purchaseService, IOmsInventoryService inventoryService, IPurchaseItemService purchaseItemService, IOmsInventoryService iOmsInventoryService) {

        this.omsPurchaseReturnItemService = omsPurchaseReturnItemService;
        this.iOmsPurchaseReturnItemService = iOmsPurchaseReturnItemService;
        this.inboundService = inboundService;
        this.inboundItemService = inboundItemService;
        this.purchaseService = purchaseService;
        this.inventoryService = inventoryService;

        this.purchaseItemService = purchaseItemService;
        this.iOmsInventoryService = iOmsInventoryService;
    }

    /**
     * 保存
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor={Exception.class})
    public boolean save(OmsPurchaseReturn entity) {
        if(StringUtils.isBlank(entity.getCode())){
            entity.setCode(IdUtil.simpleUUID());
        }
        if(StringUtils.isBlank(entity.getCreatedBy())){
            entity.setCreatedBy(UserUtil.getCode());
        }
        return super.save(entity);
    }





    /**
     * 保存采购退货单
     * @param entity
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(OmsPurchaseReturn entity) {
        //检查提交的是否有重复项
        CheckDuplicatedata(entity);
        //检查该采购退货单是否满足退单条件
        checkSaleReturnNum(entity);
        calcQuantity(entity);
        if (StrUtil.isNotBlank(entity.getCode())) {
            //先判断是否有保存的的该采购退货单
            OmsPurchaseReturn omsPurchaseReturn=getOneByCode(entity.getCode());
            if (ObjectUtil.isEmpty(omsPurchaseReturn)){
                log.error("采购单保存失败：根据提供的【{}】没有查找到该采购退货单。", omsPurchaseReturn.getCode());
                throw new ServiceException("当前采购退货单不存在");
            }
            if(omsPurchaseReturn.getStatus().equals(OrderStatusEnum.PENDING)||omsPurchaseReturn.getStatus().equals(OrderStatusEnum.PASS)){
                log.error("采购退货单保存失败：采购退货单【{}】当前状态为【{}】不能发起修改操作。",omsPurchaseReturn.getCode(),omsPurchaseReturn.getStatus());
                throw new ServiceException("采购退货单信息当前状态不满足保存条件");
            }
            entity.setGroupCode(UserUtil.getBranchCode());
            entity.setModifiedBy(UserUtil.getCode());
            entity.setModifiedName(partyCache.translate(UserUtil.getCode()));
            entity.setStatus(OrderStatusEnum.NEWS);
            this.updateByCode(entity);
            //清除原有所有明细
            omsPurchaseReturnItemService.remove(new QueryWrapper<OmsPurchaseReturnItem>().lambda().eq(OmsPurchaseReturnItem::getPurchaseReturnCode, entity.getCode()));
        }else{
            entity.setCode(OrderIdGeneratorUtil.generatorOmsOrderId(OrderIdGeneratorUtil.OrderTypeEnum.PT, "", UserUtil.getBranchCode()));
            entity.setGroupCode(UserUtil.getBranchCode());
            entity.setCreatedBy(UserUtil.getCode());
            entity.setCreatedName(partyCache.translate(UserUtil.getCode()));
            entity.setModifiedBy(UserUtil.getCode());
            entity.setStatus(OrderStatusEnum.NEWS);

            entity.setPurchaseReturnType(PurchaseTypeEnum.PURCHASERETURNS);
            entity.setModifiedName(partyCache.translate(UserUtil.getCode()));
            //保存采购退货单
            save(entity);
        }
        entity.getOmsPurchaseReturnItemList().forEach(r -> {
            r.setCode(IdUtil.simpleUUID());
            r.setPurchaseReturnCode(entity.getCode());
            r.setCreatedBy(entity.getCreatedBy());
            r.setCreatedName(entity.getCreatedName());
            r.setModifiedBy(entity.getModifiedBy());
            r.setModifiedName(entity.getModifiedName());
        });
        //保存采购明细
        omsPurchaseReturnItemService.saveBatch(entity.getOmsPurchaseReturnItemList());

    }

    /***
     * 提交采购退货单
     * @param entity
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submit(OmsPurchaseReturn entity ) {
        //检查提交的是否有重复项
        CheckDuplicatedata(entity);
        //判断是否满足采购退货单条件
         checkSaleReturnNum(entity);
         //把重新计算的数量进行赋值
        calcQuantity(entity);
        //检查并占用库存
        validSaleInventory(entity);

        if (StrUtil.isNotBlank(entity.getCode())) {
            OmsPurchaseReturnVO check = getByCode(entity.getCode());
            if (check.getCode()== null) {
                log.error("采购单提交失败：根据提供的code没有查找到该采购单。", entity.getCode(), check.getStatus());
                throw new ServiceException("当前采购单不存在");
            }
            //获取采购单信息
            if ( check.getStatus().equals(OrderStatusEnum.PENDING)||check.getStatus().equals(OrderStatusEnum.PASS)) {
                log.error("采购单提交失败：采购单【{}】当前状态为【{}】不能发起提交操作。", entity.getCode(), check.getStatus());
                throw new ServiceException("采购单退单当前状态不能提交");
            }
            entity.setModifiedBy(UserUtil.getCode());
            entity.setModifiedName(partyCache.translate(UserUtil.getCode()));
            entity.setStatus(OrderStatusEnum.PENDING);
            //
            this.updateByCode(entity);
            BigDecimal  refundQuantitysum=BigDecimal.ZERO;
            BigDecimal  refundBasicQuantitysum=BigDecimal.ZERO;
             for (OmsPurchaseReturnItem r: entity.getOmsPurchaseReturnItemList()) {
                BigDecimal  refundQuantity=BigDecimal.ZERO;
                BigDecimal   newPlanQuantity;
                BigDecimal  refundBasicQuantity=BigDecimal.ZERO;
                BigDecimal   newPlanBasicQuantity;
                //查询传输过来的计划数量
                newPlanQuantity=r.getPlanQuantity();
                newPlanBasicQuantity=r.getPlanBasicQuantity();
                PurchaseItem purchaseItem =purchaseItemService.getOne(new QueryWrapper<PurchaseItem>().lambda().eq(PurchaseItem::getPurchaseCode,entity.getSourceCode())
                        .eq(PurchaseItem::getDeleted,0).eq(PurchaseItem::getCode,r.getSourceItemCode()));
                if (ObjectUtil.isNotEmpty(purchaseItem)){
                    refundBasicQuantity=purchaseItem.getRefundBasicQuantity();
                    refundQuantity=purchaseItem.getRefundQuantity();
                }
                BigDecimal  finalPlanQuantity=refundQuantity.add(newPlanQuantity);
                BigDecimal  finalPlanQuantityBaisic=refundBasicQuantity.add(newPlanBasicQuantity);
                 refundQuantitysum=refundQuantitysum.add(finalPlanQuantity);
                 refundBasicQuantitysum=refundBasicQuantitysum.add(finalPlanQuantityBaisic);
                //查询对应的采购单，修改退货数量
                purchaseItemService.update(new UpdateWrapper<PurchaseItem>().lambda()
                        .eq(PurchaseItem::getPurchaseCode,entity.getSourceCode()).eq(PurchaseItem::getDeleted,0).eq(PurchaseItem::getCode,r.getSourceItemCode())
                        .set(PurchaseItem::getRefundQuantity,finalPlanQuantity).set(PurchaseItem::getRefundBasicQuantity, finalPlanQuantityBaisic));
            }
            //修改退货主端的退货数量
            purchaseService.update(new UpdateWrapper<Purchase>().lambda()
                    .eq(Purchase::getCode,entity.getSourceCode())
                    .set(Purchase::getRefundQuantity,refundQuantitysum).set(Purchase::getRefundBasicQuantity, refundBasicQuantitysum));
            //清除原有所有明细
            omsPurchaseReturnItemService.remove(new QueryWrapper<OmsPurchaseReturnItem>().lambda().eq(OmsPurchaseReturnItem::getPurchaseReturnCode, entity.getCode()));
        }else{
            entity.setCode(OrderIdGeneratorUtil.generatorOmsOrderId(OrderIdGeneratorUtil.OrderTypeEnum.PT, "", UserUtil.getBranchCode()));
            entity.setGroupCode(UserUtil.getBranchCode());
            entity.setCreatedBy(UserUtil.getCode());
            entity.setPurchaseReturnType(PurchaseTypeEnum.PURCHASERETURNS);
            entity.setStatus(OrderStatusEnum.PENDING);
            entity.setCreatedName(partyCache.translate(UserUtil.getCode()));
            entity.setModifiedBy(UserUtil.getCode());
            entity.setModifiedName(partyCache.translate(UserUtil.getCode()));
            save(entity);
            BigDecimal  refundQuantitysum=BigDecimal.ZERO;
            BigDecimal  refundBasicQuantitysum=BigDecimal.ZERO;
            for (OmsPurchaseReturnItem r: entity.getOmsPurchaseReturnItemList()) {
                //查询对应的采购单，修改退货数量
                BigDecimal  refundQuantity=BigDecimal.ZERO;
                BigDecimal   newPlanQuantity;
                BigDecimal  refundBasicQuantity=BigDecimal.ZERO;
                BigDecimal   newPlanBasicQuantity;
                //查询传输过来的计划数量
                newPlanQuantity=r.getPlanQuantity();
                newPlanBasicQuantity=r.getPlanBasicQuantity();
                PurchaseItem purchaseItem =purchaseItemService.getOne(new QueryWrapper<PurchaseItem>().lambda().eq(PurchaseItem::getPurchaseCode,entity.getSourceCode()).eq(PurchaseItem::getDeleted,0).eq(PurchaseItem::getCode,r.getSourceItemCode()));
                if (ObjectUtil.isNotEmpty(purchaseItem)){
                    refundBasicQuantity=purchaseItem.getRefundBasicQuantity();
                    refundQuantity=purchaseItem.getRefundQuantity();
                }
                BigDecimal  finalPlanQuantity=refundQuantity.add(newPlanQuantity);
                BigDecimal  finalPlanQuantityBaisic=refundBasicQuantity.add(newPlanBasicQuantity);
                refundQuantitysum=refundQuantitysum.add(finalPlanQuantity);
                refundBasicQuantitysum=refundBasicQuantitysum.add(finalPlanQuantityBaisic);
                //查询对应的采购单，修改退货数量
                purchaseItemService.update(new UpdateWrapper<PurchaseItem>().lambda().eq(PurchaseItem::getPurchaseCode,entity.getSourceCode()).eq(PurchaseItem::getDeleted,0).eq(PurchaseItem::getCode,r.getSourceItemCode())
                        .set(PurchaseItem::getRefundQuantity,finalPlanQuantity).set(PurchaseItem::getRefundBasicQuantity, finalPlanQuantityBaisic));
            }


            //修改退货主端的退货数量
            purchaseService.update(new UpdateWrapper<Purchase>().lambda()
                    .eq(Purchase::getCode,entity.getSourceCode())
                    .set(Purchase::getRefundQuantity,refundQuantitysum).set(Purchase::getRefundBasicQuantity, refundBasicQuantitysum));
        }

        entity.getOmsPurchaseReturnItemList().forEach(r -> {
            r.setCode(IdUtil.simpleUUID());
            r.setPurchaseReturnCode(entity.getCode());
            r.setCreatedBy(entity.getCreatedBy());
            r.setCreatedName(entity.getCreatedName());
            r.setModifiedBy(entity.getModifiedBy());
            r.setModifiedName(entity.getModifiedName());
        });
        //保存采购明细
        omsPurchaseReturnItemService.saveBatch(entity.getOmsPurchaseReturnItemList());
        //修改库存

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void annul(String code) {
        OmsPurchaseReturn  omsPurchaseReturn =getOne(new QueryWrapper<OmsPurchaseReturn>().lambda().eq(OmsPurchaseReturn::getCode,code)
                .in(OmsPurchaseReturn::getStatus,OrderStatusEnum.NEWS,OrderStatusEnum.NO_PASS));
        if (ObjectUtil.isEmpty(omsPurchaseReturn)){
            throw new ServiceException("采购单退货单不存在或当前状态不允许作废");
        }else{
            omsPurchaseReturn.setStatus(OrderStatusEnum.ANNUL);
            updateByCode(omsPurchaseReturn);
        }
    }
    /**
     * 根据code更新实体
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor={Exception.class})
    public int updateByCode(OmsPurchaseReturn entity) {
        if(StringUtils.isBlank(entity.getModifiedBy())){
            entity.setModifiedBy(UserUtil.getCode());
        }
        return baseMapper.update(entity,new QueryWrapper<OmsPurchaseReturn>().lambda().eq(OmsPurchaseReturn::getCode,entity.getCode()));
    }

    /**
     * 查询列表
     * @param omsPurchaseReturnDTO
     * @return
     */
    @Override
    public List<OmsPurchaseReturnVO> queryList(OmsPurchaseReturnDTO omsPurchaseReturnDTO){
        //排序字段名需要驼峰转数据库下划线类型字段名
        if(StringUtils.isNotEmpty(omsPurchaseReturnDTO.getSortField())){
            omsPurchaseReturnDTO.setSortField(CommonUtil.camel2Underline(omsPurchaseReturnDTO.getSortField()));
        }
        List<OmsPurchaseReturnVO> omsPurchaseReturnVOList = baseMapper.queryList(omsPurchaseReturnDTO);
        //omsPurchaseReturnVOList.stream().forEach(r->{
        //    r.setWarehouseName(warehouseCache.translate(r.getWarehouseCode()));
        //});
        return omsPurchaseReturnVOList;
    }

    /**
     * 查询合计,包含总数
     * @param omsPurchaseReturnDTO
     * @return
     */
    @Override
    public OmsPurchaseReturnVO queryListSum(OmsPurchaseReturnDTO omsPurchaseReturnDTO){
        OmsPurchaseReturnVO omsPurchaseReturnVO = baseMapper.queryListSum(omsPurchaseReturnDTO);
        return omsPurchaseReturnVO;
    }



    @Transactional(rollbackFor = {Exception.class})
    public void checkSaleReturnNum(OmsPurchaseReturn entity) {
        // 根据采购退货单，获取有效的采购单明细信息， 然后用"商品code-商品单位"做key， 判断 现有可退数量 与提供的 退货数量 差值
        Purchase  purchase=purchaseService.getOne(new QueryWrapper<Purchase>().lambda().eq(Purchase::getCode,entity.getSourceCode()).eq(Purchase::getDeleted,0));
        if (purchase == null) {
            throw new ServiceException("该退单对应的采购单不存在，请检查");
        }
        //采购退货单明细
        List<OmsPurchaseReturnItem> itemList = entity.getOmsPurchaseReturnItemList();

        // 校验退货数量
        itemList.forEach(e -> {
            if (e.getPlanQuantity() == null || e.getPlanQuantity().compareTo(BigDecimal.ZERO) <= 0) {
                throw new ServiceException("采购退货数量必须大于0");
            }
        });


        //查询有效的采购单明细
        List<PurchaseItem>  purchaseItemList = purchaseItemService.list(new QueryWrapper<PurchaseItem>().lambda()
                .eq(PurchaseItem::getPurchaseCode, entity.getSourceCode())
                .eq(PurchaseItem::getDeleted, 0)
                .gt(PurchaseItem::getPlanQuantity, 0));
        Map<String, BigDecimal> purchaseItemInfo = new HashMap<>();
        // 根据订单明细生成 以“商品code-商品单位code" 为key，出货数量为value的map，用于下一步计算；
        purchaseItemList.forEach(e -> {
            purchaseItemInfo.put(e.getGoodsCode() + "-" + e.getBasicUnit(), e.getActualQuantity().subtract(e.getRefundQuantity()));
        });
        // 遍历判断商品是否超出可退数量
        BigDecimal newRefundQuantity;
        //遍历采购退货单明细
        for (OmsPurchaseReturnItem item : itemList) {
           newRefundQuantity = item.getPlanQuantity();
            BigDecimal canRefundQuantity = purchaseItemInfo.get(item.getGoodsCode() + "-" + item.getBasicUnit());
            if(canRefundQuantity==null){
                throw new ServiceException("采购退货商品：\"" + item.getGoodsName() + "\"不在对应采购单中，请确认");
            }
            if (canRefundQuantity.compareTo(newRefundQuantity) < 0) {
                // 拟退数量超过了可退数量
                throw new ServiceException("商品：\"" + item.getGoodsName() + "\"超过了可退数量，请确认");
            }
        }

    }




    @Override
    public  OmsPurchaseReturnVO getByCode(String code) {
        OmsPurchaseReturnVO   omsPurchaseReturnVO = new OmsPurchaseReturnVO();
        OmsPurchaseReturn omsPurchaseReturn = getOneByCode(code);
        omsPurchaseReturnVO.setWarehouseName(warehouseCache.translate(omsPurchaseReturn.getWarehouseCode()));
        BeanUtil.copyProperties(omsPurchaseReturn, omsPurchaseReturnVO, false);
        omsPurchaseReturnVO.setSupplierName(supplierCache.translate(omsPurchaseReturn.getSupplierCode()));
        omsPurchaseReturnVO.getOmsPurchaseReturnItemList().forEach(e->{
            Double refundableQuantity = iOmsPurchaseReturnItemService.queryRefundableQuantity(e.getCode());
            e.setRefundableQuantity( BigDecimal.valueOf(refundableQuantity));
        });
        return omsPurchaseReturnVO;
    }



    @Override
    public OmsPurchaseReturn getOneByCode(String code) {
        OmsPurchaseReturn purchaseReturn = getOne(new QueryWrapper<OmsPurchaseReturn>().lambda().eq(OmsPurchaseReturn::getCode, code));
        if (purchaseReturn != null) {
            List<OmsPurchaseReturnItem> omsPurchaseReturnItemList = omsPurchaseReturnItemService.list(new QueryWrapper<OmsPurchaseReturnItem>().lambda().eq(OmsPurchaseReturnItem::getPurchaseReturnCode, purchaseReturn.getCode()));
            purchaseReturn.setOmsPurchaseReturnItemList(omsPurchaseReturnItemList);
            return purchaseReturn;
        }
        return null;
    }



    public void calcQuantity(OmsPurchaseReturn entity) {
        // 计算订单总数（销售单位、基本单位）
        BigDecimal planQuantity = BigDecimal.ZERO, planBasicQuantity = BigDecimal.ZERO;
        Goods goods;
        Integer unitPrecision;
        for(OmsPurchaseReturnItem e: entity.getOmsPurchaseReturnItemList()){
            // 根据转换率、单价、税率等，需要计算出基本单位的数量、总价等信息
            goods = goodsCache.getObj(e.getGoodsCode());
            if (ObjectUtil.isNull(goods)) {
                throw new ServiceException("商品【" + e.getGoodsName() + "】信息不存在");
            }
            // 处理商品数量精度
            unitPrecision = goods.getUnitPrecision().intValue();
            e.setPlanBasicQuantity(e.getPlanQuantity().multiply(e.getUnitConvertQuantity()).setScale(unitPrecision, BigDecimal.ROUND_HALF_UP));

            // 含税单价 = 单价*税率/100
            e.setTaxUnitPrice(e.getUnitPrice().multiply(e.getTaxRate()).divide(DECIMAL100).add(e.getUnitPrice()).setScale(6, BigDecimal.ROUND_HALF_UP));
            // 金额 = 单价*销售数量
            e.setAmountMoney(e.getUnitPrice().multiply(e.getPlanQuantity()).setScale(6, BigDecimal.ROUND_HALF_UP));

            // 税额 = 单价*销售数量*税率/100  保留6位小数
            e.setTaxMoney(e.getUnitPrice().multiply(e.getPlanQuantity()).multiply(e.getTaxRate()).divide(DECIMAL100).setScale(6, BigDecimal.ROUND_HALF_UP));
            // 价税合计 = 金额 + 税额 ; 重新再计算一遍，避免前面保留小数位数造成精度丢失
            e.setTotalMoney(e.getUnitPrice().multiply(e.getPlanQuantity()).add(
                    e.getUnitPrice().multiply(e.getPlanQuantity()).multiply(e.getTaxRate()).divide(DECIMAL100)
            ).setScale(6, BigDecimal.ROUND_HALF_UP));

            // 计算计划总量
            planQuantity = planQuantity.add(e.getPlanQuantity()).setScale(unitPrecision, BigDecimal.ROUND_HALF_UP);
            planBasicQuantity = planBasicQuantity.add(e.getPlanBasicQuantity()).setScale(unitPrecision, BigDecimal.ROUND_HALF_UP);
        }
        entity.setPlanQuantity(planQuantity);
        entity.setPlanBasicQuantity(planBasicQuantity);
    }


    public void   CheckDuplicatedata(OmsPurchaseReturn entity){
        List<OmsPurchaseReturnItem> omsPurchaseReturnItemList = entity.getOmsPurchaseReturnItemList();
        Map<String, Object> validDuplication = new HashMap<>();
        String validKey;
        for(OmsPurchaseReturnItem e : omsPurchaseReturnItemList){
            validKey = e.getGoodCode() + "-" + e.getBasicUnit();
            if(validDuplication.containsKey(validKey)){
                throw new ServiceException("存在重复的商品信息，请确认");
            }else{
                validDuplication.put(validKey, e);
            }
        }

    }

    /***
     * 审核采购退货单号
     * @param code
     * @param status
     * @param opinion
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void verify(String code, String status, String opinion) {
        //根据code查询采购退货单
        OmsPurchaseReturnVO purchaseReturnVO=getByCode(code);
        if (ObjectUtil.isEmpty(purchaseReturnVO)){
            log.info("采购退货单审核失败：采购退货单【{}】找不到",code);
            throw new ServiceException("找不到采购单信息");
        }
        //待审核状态的才能发起审核
        if(!purchaseReturnVO.getStatus().equals(OrderStatusEnum.PENDING)){
            log.error("采购退货单审核失败：采购退货单【{}】当前状态为【{}】不能发起审核操作。",purchaseReturnVO.getCode(),purchaseReturnVO.getStatus());
            throw new ServiceException("当前采购单退货单不满足审核状态");
        }
        if(OrderStatusEnum.PASS.getValue().equals(status)){//审核通过
            //判断仓库是否启用库位管理
            Map<String, Object> warehouseMap = warehouseCache.get(purchaseReturnVO.getWarehouseCode());
            if (MapUtil.isEmpty(warehouseMap)) {
                log.error("采购退货单审核失败：采购单【{}】所属仓库【{}】找不到。",purchaseReturnVO.getCode(),purchaseReturnVO.getWarehouseCode());
                throw new ServiceException("找不到仓库信息");
            }
            Warehouse warehouse = BeanUtil.mapToBean(warehouseMap, Warehouse.class, false);
            //更新采购退货单审核结果
            update(new UpdateWrapper<OmsPurchaseReturn>().lambda()
                    .eq(OmsPurchaseReturn::getCode, code)
                    .set(OmsPurchaseReturn::getStatus, OrderStatusEnum.PASS)
                    .set(OmsPurchaseReturn::getVerifyOpinion, opinion)
                    .set(OmsPurchaseReturn::getGmtVerify, LocalDateTime.now())
                    .set(OmsPurchaseReturn::getVerifyBy, UserUtil.getCode())
                    .set(OmsPurchaseReturn::getVerifyName, partyCache.translate(UserUtil.getCode())));
            //启用库位管理:0不启用，1启用
            int locationManagement = warehouse.getLocationManagement();
            if(0==locationManagement) {
                //不启动仓库库位,直接生成入库单(负的)
                OmsInbound omsInbound = new OmsInbound();
                BeanUtils.copyProperties(purchaseReturnVO, omsInbound);
                omsInbound.setCode(OrderIdGeneratorUtil.generatorOmsOrderId(OrderIdGeneratorUtil.OrderTypeEnum.RK, "", UserUtil.getBranchCode()));
                omsInbound.setShipmentCode(purchaseReturnVO.getShipmentCode());
                omsInbound.setShipmentName(purchaseReturnVO.getShipmentName());
                omsInbound.setWarehouseCode(purchaseReturnVO.getWarehouseCode());
                omsInbound.setSourceCode(purchaseReturnVO.getCode());
                omsInbound.setType(PurchaseTypeEnum.PURCHASERETURNS.getValue());
                omsInbound.setCreatedBy(UserUtil.getCode());
                omsInbound.setCreatedName(partyCache.translate(UserUtil.getCode()));
                omsInbound.setModifiedBy(UserUtil.getCode());
                omsInbound.setModifiedName(partyCache.translate(UserUtil.getCode()));
                omsInbound.setStatus(InboundStatusEnum.FINISH_IN.getValue());
                omsInbound.setPaymentAmount(BigDecimal.ZERO);

                BigDecimal owedAmount=BigDecimal.ZERO;
                //保存入库单明细
                List<OmsInboundItem> inboundItems = purchaseReturnVO.getOmsPurchaseReturnItemList().stream().map(r -> {
                    OmsInboundItem item = new OmsInboundItem();
                    BeanUtil.copyProperties(r, item, false);
                    item.setCode(IdUtil.simpleUUID());
                    item.setInboundCode(omsInbound.getCode());
                    item.setStorageQuantity(r.getPlanBasicQuantity().negate()); //负数
                    item.setTaxMoney(r.getUnitPrice().multiply(r.getPlanQuantity()).multiply(r.getTaxRate())
                            .divide(DECIMAL100).setScale(6, BigDecimal.ROUND_HALF_UP).negate());
                    item.setAmountMoney(r.getUnitPrice().multiply(r.getPlanQuantity()).setScale(6, BigDecimal.ROUND_HALF_UP).negate());
                    item.setTotalMoney(r.getUnitPrice().multiply(r.getPlanQuantity()).add(
                            r.getUnitPrice().multiply(r.getPlanQuantity()).multiply(r.getTaxRate()).divide(DECIMAL100)
                    ).setScale(6, BigDecimal.ROUND_HALF_UP).negate());
                    item.setCreatedBy(UserUtil.getCode());
                    item.setCreatedName(partyCache.translate(UserUtil.getCode()));
                    item.setModifiedBy(UserUtil.getCode());
                    item.setModifiedName(partyCache.translate(UserUtil.getCode()));
                    return item;
                }).collect(Collectors.toList());
                //保存入库单明细
                inboundItemService.saveBatch(inboundItems);
                for(OmsInboundItem e:inboundItems){
                    owedAmount=owedAmount.add(e.getTotalMoney());
                }
                omsInbound.setOwedAmount(owedAmount);
                //保存入库单
                inboundService.save(omsInbound);
                //更新库存
                inboundItems.forEach(r -> {
                    OmsInventory inventory = inventoryService.getOne(new QueryWrapper<OmsInventory>().lambda().eq(OmsInventory::getGoodsCode, r.getGoodsCode())
                    .eq(OmsInventory::getWarehouseCode,omsInbound.getWarehouseCode()).eq(OmsInventory::getShipmentCode,omsInbound.getShipmentCode()));
                    if (inventory != null) {
                        //如果有库存记录,更新库存
                        inventoryService.update(new UpdateWrapper<OmsInventory>().lambda().eq( OmsInventory::getGoodsCode, inventory.getGoodsCode())
                                .eq(OmsInventory::getWarehouseCode,omsInbound.getWarehouseCode())
                                .eq(OmsInventory::getShipmentCode,omsInbound.getShipmentCode())
                                .setSql("quantity=quantity+" + r.getStorageQuantity())
                                .setSql("use_quantity = use_quantity + " + r.getStorageQuantity() )
                                .setSql("average_unit_price = (total_amount+"+r.getTotalMoney()+")/quantity")
                                .setSql("total_amount = average_unit_price * quantity"));
                    } else {
                        throw new ServiceException("商品“" + r.getGoodsName() + "”可用库存不足。");
                    }
                });
                //更新采购退货单明细实际采购数量，入库数量，合计金额(不用修改采购单的退货数量)
                purchaseReturnVO.getOmsPurchaseReturnItemList().forEach(r -> {
                    //根据实际采购数量计算税额
                    BigDecimal taxMoney = r.getPlanQuantity().multiply(r.getTaxUnitPrice());
                    //根据实际采购数量计算金额
                    BigDecimal amountMoney = r.getPlanQuantity().multiply(r.getUnitPrice());
                    //根据实际采购数量计算价税合计
                    BigDecimal totalMoney = r.getPlanQuantity().multiply(r.getTaxUnitPrice());
                    omsPurchaseReturnItemService.update(new UpdateWrapper<OmsPurchaseReturnItem>().lambda()
                            .eq(OmsPurchaseReturnItem::getCode, r.getCode())
                            .set(OmsPurchaseReturnItem::getTaxMoney, taxMoney)
                            .set(OmsPurchaseReturnItem::getAmountMoney, amountMoney)
                            .set(OmsPurchaseReturnItem::getTotalMoney, totalMoney)
                            .set(OmsPurchaseReturnItem::getActualQuantity, r.getPlanQuantity())
                            .set(OmsPurchaseReturnItem::getActualBasicQuantity, r.getPlanBasicQuantity())
                    );

//                    purchaseItemService.update(new UpdateWrapper<PurchaseItem>().lambda()
//                            .eq(PurchaseItem::getCode, r.getSourceItemCode())
//                            .setSql(" refund_quantity = refund_quantity +" + r.getPlanQuantity())
//                            .setSql(" refund_basic_quantity = refund_basic_quantity + " + r.getPlanBasicQuantity())
//                    );
                });
                //更新采购退货单实际采购退货数量,
                update(new UpdateWrapper<OmsPurchaseReturn>().lambda().eq(OmsPurchaseReturn::getCode,purchaseReturnVO.getCode())
                        .set(OmsPurchaseReturn::getActualQuantity, purchaseReturnVO.getPlanQuantity())
                        .set(OmsPurchaseReturn::getActualBasicQuantity, purchaseReturnVO.getPlanBasicQuantity())
                );

//                //更新采购单的实际退货明细
//                purchaseService.update(new UpdateWrapper<Purchase>().lambda().eq(Purchase::getCode,purchaseReturnVO.getSourceCode())
//                        .setSql(" refund_quantity = refund_quantity +" + purchaseReturnVO.getPlanQuantity())
//                        .setSql(" refund_basic_quantity = refund_basic_quantity + " + purchaseReturnVO.getPlanBasicQuantity())
//                );

                // 生成OMS付款信息
                omsSettlementService.generatePayment(omsInbound);

            }else{
                //启用： 生成WMS发货单(采购退货)
                Delivery delivery =new Delivery();
                delivery.setCode(OrderIdGeneratorUtil.generatorOrderId(OrderIdGeneratorUtil.OrderTypeEnum.FH, "", UserUtil.getBranchCode()));
                delivery.setType(DeliveryTypeEnum.PURCHASE.getValue());
                delivery.setWarehouseCode(purchaseReturnVO.getWarehouseCode());
                delivery.setShipmentCode(purchaseReturnVO.getShipmentCode());
                delivery.setShipmentName(purchaseReturnVO.getShipmentName());
                delivery.setGroupCode(purchaseReturnVO.getGroupCode());
                delivery.setSourceCode(purchaseReturnVO.getCode());
                delivery.setCreatedBy(purchaseReturnVO.getVerifyBy());
                delivery.setCreatedName(purchaseReturnVO.getVerifyName());
                delivery.setModifiedBy(purchaseReturnVO.getVerifyBy());
                delivery.setModifiedName(purchaseReturnVO.getVerifyName());
                delivery.setRefundQuantity(purchaseReturnVO.getPlanQuantity());
                delivery.setIsOmsOrder(1);
                delivery.setStatus(DeliveryStatusEnum.UN_DISTRIBUTION.getValue());
                delivery.setTotalNum(purchaseReturnVO.getPlanBasicQuantity());
                // 保存发货单
                deliveryService.save(delivery);
                // 生成发货单明细
                List<OmsPurchaseReturnItem> omsPurchaseReturnServiceList = omsPurchaseReturnItemService.list(new QueryWrapper<OmsPurchaseReturnItem>().lambda().eq(OmsPurchaseReturnItem::getPurchaseReturnCode, purchaseReturnVO.getCode()));
                List<DeliveryItem> deliveryItemList = Lists.newArrayList();
                omsPurchaseReturnServiceList.stream().forEach(item -> {
                    DeliveryItem deliveryItem = new DeliveryItem();
                    BeanUtils.copyProperties(item, deliveryItem);
                    deliveryItem.setCode(IdUtil.simpleUUID());
                    deliveryItem.setDeliveryCode(delivery.getCode());
                    deliveryItem.setSourceItemCode(item.getCode());
                    deliveryItem.setGoodsCode(item.getGoodsCode());
                    deliveryItem.setGoodCode(item.getGoodCode());
                    deliveryItem.setGoodsName(item.getGoodsName());
                    deliveryItem.setGoodsBarCode(item.getGoodsBarCode());
                    deliveryItem.setSpec(item.getSpec());
                    deliveryItem.setExpirationQuantity(item.getExpirationQuantity());
                    deliveryItem.setGoodsUnit(item.getReturnUnit());
                    deliveryItem.setGoodsUnitName(item.getReturnUnitName());
                    deliveryItem.setBasicUnit(item.getBasicUnit());
                    deliveryItem.setBasicUnitName(item.getBasicUnitName());
                    deliveryItem.setBasicQuantity(item.getUnitConvertQuantity());
                    deliveryItem.setQuantity(item.getPlanQuantity());
                    deliveryItem.setTotalNum(item.getPlanBasicQuantity());
                    deliveryItem.setCreatedBy(UserUtil.getCode());
                    deliveryItem.setGmtCreated(LocalDateTime.now());
                    deliveryItemList.add(deliveryItem);
                });

                //保存发货单明细
                deliveryItemService.saveBatch(deliveryItemList);
            }

        }else{ //审核不通过
            //释放库存
            releaseUseQuantity(purchaseReturnVO);
            BigDecimal  refundQuantitysum=BigDecimal.ZERO;
            BigDecimal  refundBasicQuantitysum=BigDecimal.ZERO;
            //更新对应采购单的退货数量
            for (OmsPurchaseReturnItemVO r :purchaseReturnVO.getOmsPurchaseReturnItemList())  {
                //查询对应的采购单，修改退货数量
                BigDecimal  refundQuantity=BigDecimal.ZERO;
                BigDecimal   newPlanQuantity;
                BigDecimal  refundBasicQuantity=BigDecimal.ZERO;
                BigDecimal   newPlanBasicQuantity;
                //查询传输过来的计划数量
                newPlanQuantity=r.getPlanQuantity();
                newPlanBasicQuantity=r.getPlanBasicQuantity();
                //采购单的退货数量
                PurchaseItem purchaseItem =purchaseItemService.getOne(new QueryWrapper<PurchaseItem>().lambda().eq(PurchaseItem::getPurchaseCode,purchaseReturnVO.getSourceCode()).eq(PurchaseItem::getDeleted,0).eq(PurchaseItem::getCode,r.getSourceItemCode()));
                if (ObjectUtil.isNotEmpty(purchaseItem)){
                    refundBasicQuantity=purchaseItem.getRefundBasicQuantity();
                    refundQuantity=purchaseItem.getRefundQuantity();
                }

                BigDecimal  finalPlanQuantity=refundQuantity.subtract(newPlanQuantity);

                BigDecimal  finalPlanQuantityBaisic=refundBasicQuantity.subtract(newPlanBasicQuantity);
                refundQuantitysum=refundQuantitysum.add(finalPlanQuantity);
                refundBasicQuantitysum=refundBasicQuantitysum.add(finalPlanQuantityBaisic);
                //查询对应的采购单，修改退货数量
                purchaseItemService.update(new UpdateWrapper<PurchaseItem>().lambda().eq(PurchaseItem::getPurchaseCode,purchaseReturnVO.getSourceCode()).eq(PurchaseItem::getDeleted,0).eq(PurchaseItem::getCode,r.getSourceItemCode())
                        .set(PurchaseItem::getRefundQuantity,finalPlanQuantity).set(PurchaseItem::getRefundBasicQuantity, finalPlanQuantityBaisic));
            }
            purchaseService.update(new UpdateWrapper<Purchase>().lambda()
                    .eq(Purchase::getCode,purchaseReturnVO.getSourceCode())
                    .set(Purchase::getRefundQuantity,refundQuantitysum).set(Purchase::getRefundBasicQuantity, refundBasicQuantitysum));
            //更新意见
            update(new UpdateWrapper<OmsPurchaseReturn>().lambda()
                    .eq(OmsPurchaseReturn::getCode, code)
                    .set(OmsPurchaseReturn::getStatus, OrderStatusEnum.NO_PASS)
                    .set(OmsPurchaseReturn::getVerifyOpinion, opinion));
        }



    }

    @Transactional(rollbackFor = {Exception.class})
    public void validSaleInventory(OmsPurchaseReturn omsPurchaseReturn) {

        omsPurchaseReturn.getOmsPurchaseReturnItemList().stream().forEach(e->{
            iOmsInventoryService.lockUsefulInventory(omsPurchaseReturn.getWarehouseCode(), e.getGoodsCode(), e.getGoodsName(),
                    omsPurchaseReturn.getShipmentCode(), e.getPlanBasicQuantity());
        });
}

    @Transactional(rollbackFor = {Exception.class})
    public void releaseUseQuantity(OmsPurchaseReturnVO omsPurchaseReturnVO) {
      // 遍历采购退货单明细，根据原计划数量（基本单位），释放占用量
        omsPurchaseReturnVO.getOmsPurchaseReturnItemList().forEach(e->{
            iOmsInventoryService.update(new UpdateWrapper<OmsInventory>().lambda().eq(OmsInventory::getGoodsCode, e.getGoodsCode())
                    .eq(OmsInventory::getWarehouseCode, omsPurchaseReturnVO.getWarehouseCode())
                    .eq(OmsInventory::getShipmentCode, omsPurchaseReturnVO.getShipmentCode())
                    .setSql(" use_quantity = use_quantity - " + e.getPlanBasicQuantity())
            );
        });

    }
}
